import React, { useState, useRef, useEffect, useImperativeHandle } from 'react';
import request from '@/utils/request';
import styles from './index.less';
import { isVideo, uid } from '@/utils';
import { useAliyunUpload, useAliyunUploadProps } from '../AliyunVideoUpload';
import classNames from 'classnames';
import { usePlvUpload, usePlvUploadProps } from '../PlvVideoUpload';
import md5 from 'crypto-js/md5';

export interface InnterUploadProps {
  action: string;
  name?: string;
  data?: (file) => Record<string, any> | Record<string, any>;
  fileList?: any[];
  className?: string;
  onChange?: (fileList: any[]) => void;
  onSuccess?: (fileList: any[], file) => void;

  beforeUpload?: (file, fileList) => Promise<boolean>;
  multiple?: boolean;
  /**
   * 视频传到哪个服务器
   */
  videoUploadto?: 'normal' | 'Aliyun' | 'Plv';
  getAliyunAuth?: useAliyunUploadProps['getAliyunAuth'];
  refreshAliyunAuth?: useAliyunUploadProps['refreshAliyunAuth'];
  getPlvAuth?: usePlvUploadProps['getPlvAuth'];
  refreshPlvAuth?: usePlvUploadProps['refreshPlvAuth'];
  children?: any;
  disabled?: boolean;
}

interface InnterUploadForwardRefProps {
  stopFile: (file) => boolean;
}

const Index = React.forwardRef<InnterUploadForwardRefProps, InnterUploadProps>(
  (
    {
      action,
      name = 'file',
      data = {},
      fileList: propsFilelist,
      className,
      children,
      videoUploadto = 'normal',
      multiple = true,
      beforeUpload,
      onSuccess,
      onChange,
      getAliyunAuth,
      refreshAliyunAuth,
      getPlvAuth,
      refreshPlvAuth,
      disabled,
    },
    ref,
  ) => {
    const [fileList, setFlieList] = useState<any>([]);
    const fileListRef = useRef<any>([]);
    const handleChange = (fileList) => {
      setFlieList([...fileList]);
      onChange?.([...fileList]);
    };

    // 阿里云点播上传
    const { AliyunUploaderRef } = useAliyunUpload({
      region: 'cn-shanghai',
      userId: '1303984639806000',
      getAliyunAuth,
      refreshAliyunAuth,
      onChange: (_, file) => {
        const index = fileListRef.current?.findIndex((item) => item.uid === file.uid);

        if (index >= 0) {
          const newFileList = [...fileListRef.current];
          newFileList[index] = file;
          handleChange(newFileList);
        }
      },
      onSuccess: (file) => {
        onSuccess?.([...fileListRef.current], file);
      },
    });

    // 保利威云点播上传
    // https://help.polyv.net/index.html#/vod/upload_js/web_upload_sdk
    const { PlvUploaderRef } = usePlvUpload({
      getPlvAuth,
      refreshPlvAuth,
      onChange: (_, file) => {
        const index = fileListRef.current?.findIndex((item) => item.uid === file.uid);
        if (index >= 0) {
          const newFileList = [...fileListRef.current];
          newFileList[index] = file;
          handleChange(newFileList);
        }
      },
      onSuccess: (file) => {
        onSuccess?.([...fileListRef.current], file);
      },
    });

    // 同步fileListRef
    useEffect(() => {
      if (Array.isArray(propsFilelist)) {
        setFlieList(propsFilelist);
        fileListRef.current = propsFilelist;
      }
    }, [propsFilelist]);

    const handleNormalUploadProgress = (file, e) => {
      file.percent = ((e.loaded / e.total) * 100).toFixed(0);
      handleChange(fileListRef.current);
    };

    const handleNormalUploadSuccess = (file, response) => {
      file.status = 'done';
      file.response = response;
      if (response?.data?.aid) {
        file.aid = response.data.aid;
      }

      handleChange(fileListRef.current);
      onSuccess?.([...fileListRef.current], file);
    };
    const handleNormalUploadFail = (file) => {
      file.status = 'error';
      handleChange(fileListRef.current);
    };

    // 其他文件上传
    const uploadNormal = (file) => {
      const formData = new FormData();
      const payload = typeof data === 'function' ? (data as any)?.() : data;
      if (payload) {
        for (let key in payload) {
          formData.append(key, payload[key] as any);
        }
      }
      formData.append(name, file);
      request
        .postForm<any, any>(action, formData, {
          onUploadProgress: (e) => handleNormalUploadProgress(file, e),
        })
        .then(
          (response) => {
            if (response?.success) {
              handleNormalUploadSuccess(file, response);
            } else {
              handleNormalUploadFail(file);
            }
          },
          () => {
            handleNormalUploadFail(file);
          },
        );
    };

    // 分流上传地址
    const shuntFile = async (file) => {
      file.uid = md5(file.name).toString().toUpperCase();
      if ((await beforeUpload?.(file, fileList)) === false) {
        return;
      }
      file.status = 'uploading';
      /**
       * 视频走阿里云
       */
      if (videoUploadto === 'Aliyun' && isVideo(file.name)) {
        AliyunUploaderRef.current.addFile(file, null, null, null, '{"Vod":{}}');
        AliyunUploaderRef.current.startUpload();
      } else if (videoUploadto === 'Plv' && isVideo(file.name)) {
      /**
       * 视频走保利威
       */
        if (!PlvUploaderRef.current.addFile(file)) {
          return false;
        }
      }
      // 其他走正常api
      else {
        uploadNormal(file);
      }
      return file;
    };

    const onSelectFile = async (e) => {
      const files = e.target.files;
      const arr = [...fileList];
      if (files.length <= 0) return;
      for (let i = 0; i < files.length; i++) {
        const file = files[i];
        const item = await shuntFile(file);
        if (item) {
          arr.push(item);
        }
      }
      fileListRef.current = arr;
      handleChange(arr);
      (inputRef.current as any).value = '';
    };
    const handleStopFile = (file) => {
      if (videoUploadto === 'Aliyun') {
        const list = AliyunUploaderRef.current?.listFiles() || [];
        const index = list.findIndex((item) => item.file.uid === file.uid);
        if (index >= 0) {
          AliyunUploaderRef.current?.cancelFile(index);
          list[index].status = 'stop';
          handleChange([...fileList]);
          return true;
        }
        return false;
      }
      if (videoUploadto === 'Plv') {
        const list = [...fileListRef.current];
        const index = list.findIndex((item) => item.uid === file.uid);
        if (index >= 0) {
          PlvUploaderRef.current?.stopFile(list[index]?.uploadManager?.id);
          list[index].status = 'stop';
          handleChange(list);
          return true;
        }
        return false;
      }
      return false;
    };
    const handleResumeFile = (file) => {
      if (videoUploadto === 'Aliyun') {
        const list = AliyunUploaderRef.current?.listFiles() || [];
        console.log(list);

        const index = list.findIndex((item) => item.file.uid === file.uid);

        if (index >= 0) {
          list[index].status = 'uploading';
          handleChange([...fileList]);
          AliyunUploaderRef.current?.resumeFile(index);
          AliyunUploaderRef.current?.startUpload();
          return true;
        }
        return false;
      }
      if (videoUploadto === 'Plv') {
        const list = [...fileListRef.current];
        const index = list.findIndex((item) => item.uid === file.uid);
        if (index >= 0) {
          PlvUploaderRef.current?.resumeFile(list[index]?.uploadManager?.id);
          list[index].status = 'uploading';
          handleChange(list);
          return true;
        }
        return false;
      }
      return false;
    };
    const handleRemoveFile = (file) => {
      const stateIndex = fileList.findIndex((item) => item.uid === file.uid);
      if (stateIndex >= 0) {
        const newFileList = [...fileList];
        newFileList.splice(stateIndex, 1);
        handleChange(newFileList);
      }
      if (videoUploadto === 'Aliyun') {
        const list = AliyunUploaderRef.current?.listFiles() || [];

        const index = list.findIndex((item) => item.file.uid === file.uid);

        if (index >= 0) {
          AliyunUploaderRef.current?.stopUpload();
          AliyunUploaderRef.current?.cancelFile(index);
          AliyunUploaderRef.current?.deleteFile(index);
          AliyunUploaderRef.current?.startUpload();
        }
      }
      if (videoUploadto === 'Plv') {
        const list = [...fileListRef.current];
        const index = list.findIndex((item) => item.uid === file.uid);
        if (index >= 0) {
          PlvUploaderRef.current?.stopFile(list[index]?.uploadManager?.id);
          PlvUploaderRef.current?.removeFile(list[index]?.uploadManager?.id);
        }
      }
    };

    /**
     * 供父组件调用
     */
    useImperativeHandle(ref, () => ({
      stopFile: handleStopFile,
      resumeFile: handleResumeFile,
      removeFile: handleRemoveFile,
    }));

    const inputRef = useRef<HTMLInputElement>(null);
    return (
      <div className={classNames(styles.innerUpload, className)}>
        <div className={styles.uploadWrapper}>
          <input
            className={styles.input}
            ref={inputRef}
            title=""
            disabled={disabled}
            type="file"
            onChange={onSelectFile}
            multiple={multiple}
          />
          {children}
        </div>
      </div>
    );
  },
);

export default Index;
